package com.tjs.lucky.domain.rule.service.engine;

import com.tjs.lucky.common.rule.NodeType;
import com.tjs.lucky.domain.rule.mdel.aggregates.TreeRuleRich;
import com.tjs.lucky.domain.rule.mdel.req.DecisionValueReq;
import com.tjs.lucky.domain.rule.mdel.res.EngineResult;
import com.tjs.lucky.domain.rule.mdel.vo.TreeNodeVO;
import com.tjs.lucky.domain.rule.mdel.vo.TreeRootVO;
import com.tjs.lucky.domain.rule.service.logic.LogicFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

/**
 * @Author: 田佳澍
 * @Description: 规则引擎基础类
 * @DateTime: 2023/5/29 17:28
 **/
public abstract class EngineBase extends EngineConfig implements EngineFilter {

    private final Logger logger = LoggerFactory.getLogger(EngineBase.class);

    @Override
    public EngineResult process(DecisionValueReq valueReq) {
        throw new RuntimeException("未实现规则引擎服务");
    }

    /**
     * 根据 决策树  和 决策值进行抉择
     *
     * @param treeRuleRich
     * @param valueReq
     * @return
     */
    protected TreeNodeVO engineDecisionMaker(TreeRuleRich treeRuleRich, DecisionValueReq valueReq) {
        TreeRootVO root = treeRuleRich.getTreeRoot();
        Map<Long, TreeNodeVO> treeNodeMap = treeRuleRich.getTreeNodeMap();

        // 规则树根ID
        Long rootNodeId = root.getTreeRootNodeId();
        TreeNodeVO ChildOfRoot = treeNodeMap.get(rootNodeId);

        // 节点类型[NodeType]；1子叶、2果实
        // 如果孩子结点是叶子结点就停止循环
        while (NodeType.STEM.equals(ChildOfRoot.getNodeType())) {
            // 获取决策Key
            String ruleKey = ChildOfRoot.getRuleKey();
            // 根据 决策key 获取对应的 实现对象。
            LogicFilter logicFilter = logicFilterMap.get(ruleKey);
            // 获取请求中的 决策值
            String decValue = logicFilter.getValue(valueReq);
            // 根据决策值 来决策获取哪个一个孩子结点
            Long nextRoot = logicFilter.filter(decValue, ChildOfRoot.getTreeNodeLineChildList());
            ChildOfRoot = treeNodeMap.get(nextRoot);
            logger.info("决策树引擎=>{} userId：{} treeId：{} treeNode：{} ruleKey：{} matterValue：{}", root.getTreeName(), valueReq.getUserId(), valueReq.getTreeId(), ChildOfRoot.getTreeNodeId(), ruleKey, decValue);
        }

        return ChildOfRoot;
    }

}
